﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Common
{

    public class MyBase64
    {
        static int shift = 6;
        static char[] digits = {  
        '0' , '1' , '2' , '3' , '4' , '5' ,  
        '6' , '7' , '8' , '9' , 'a' , 'b' ,  
        'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,  
        'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,  
        'o' , 'p' , 'q' , 'r' , 's' , 't' ,  
        'u' , 'v' , 'w' , 'x' , 'y' , 'z' ,  
        'A' , 'B' , 'C' , 'D' , 'E' , 'F' ,  
        'G' , 'H' , 'I' , 'J' , 'K' , 'L' ,  
        'M' , 'N' , 'O' , 'P' , 'Q' , 'R' ,  
        'S' , 'T' , 'U' , 'V' , 'W' , 'X' ,  
        'Y' , 'Z' , '!' , '@'  ,  
        };
        /** 
         * @param args 
         */
        public static void main(String[] args)
        {

        }
        /** 
         * 把10进制的数字转换成64进制 
         * @param number 
         * @param shift 
         * @return 
         */
        public static String CompressNumber(long number)
        {
            char[] buf = new char[64];
            int charPos = 64;
            int radix = 1 << shift;
            long mask = radix - 1;
            do
            {
                buf[--charPos] = digits[(int)(number & mask)];
                number = number >> shift;
            } while (number != 0);
            return new String(buf, charPos, (64 - charPos));
        }
        /** 
         * 把64进制的字符串转换成10进制 
         * @param decompStr 
         * @return 
         */
        public static long UnCompressNumber(String decompStr)
        {
            long result = 0;
            for (int i = decompStr.Length - 1; i >= 0; i--)
            {
                if (i == decompStr.Length - 1)
                {
                    result += getCharIndexNum(decompStr.ToCharArray()[i]);
                    continue;
                }
                for (int j = 0; j < digits.Length; j++)
                {
                    if (decompStr.ToCharArray()[i] == digits[j])
                    {
                        result += ((long)j) << 6 * (decompStr.Length - 1 - i);
                    }
                }
            }
            return result;
        }
        /** 
         *  
         * @param ch 
         * @return 
         */
        private static long getCharIndexNum(char ch)
        {
            int num = ((int)ch);
            if (num >= 48 && num <= 57)
            {
                return num - 48;
            }
            else if (num >= 97 && num <= 122)
            {
                return num - 87;
            }
            else if (num >= 65 && num <= 90)
            {
                return num - 29;
            }
            else if (num == 43)
            {
                return 62;
            }
            else if (num == 47)
            {
                return 63;
            }
            return 0;
        }

    }  

    public class compressEncodeing {  
     static char[] digits = {  
        '0' , '1' , '2' , '3' , '4' , '5' ,  
        '6' , '7' , '8' , '9' , 'a' , 'b' ,  
        'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,  
        'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,  
        'o' , 'p' , 'q' , 'r' , 's' , 't' ,  
        'u' , 'v' , 'w' , 'x' , 'y' , 'z' ,  
        'A' , 'B' , 'C' , 'D' , 'E' , 'F' ,  
        'G' , 'H' , 'I' , 'J' , 'K' , 'L' ,  
        'M' , 'N' , 'O' , 'P' , 'Q' , 'R' ,  
        'S' , 'T' , 'U' , 'V' , 'W' , 'X' ,  
        'Y' , 'Z' , '+' , '/'  ,  
        };  
    /** 
     * @param args 
     */  
    public static void main(String[] args) {  
        Console.WriteLine(CompressNumber(999999999999999999L,6));
        Console.WriteLine(UnCompressNumber(CompressNumber(999999999999999999L, 6)));  
    }  
    /** 
     * 把10进制的数字转换成64进制 
     * @param number 
     * @param shift 
     * @return 
     */  
    private static String CompressNumber(long number, int shift) {  
        char[] buf = new char[64];  
        int charPos = 64;  
        int radix = 1 << shift;  
        long mask = radix - 1;  
        do {  
            buf[--charPos] = digits[(int)(number & mask)];  
            number=number >> shift;
            number = number >> shift; 
        } while (number != 0);  
        return new String(buf, charPos, (64 - charPos));  
       }  
    /** 
     * 把64进制的字符串转换成10进制 
     * @param decompStr 
     * @return 
     */  
    private static long UnCompressNumber(String decompStr)  
    {  
        long result=0;  
        for (int i =  decompStr.Length-1; i >=0; i--) {
            if (i == decompStr.Length - 1)  
            {  
                result+=getCharIndexNum(decompStr.ToCharArray()[i]);  
                continue;  
            }
            for (int j = 0; j < digits.Length; j++)
            {
                if (decompStr.ToCharArray()[i] == digits[j])  
                {
                    result += ((long)j) << 6 * (decompStr.Length - 1 - i);  
                }  
            }  
        }  
        return result;  
    }     
    /** 
     *  
     * @param ch 
     * @return 
     */  
    private static long getCharIndexNum(char ch)  
    {  
        int num=((int)ch);  
        if(num>=48&&num<=57)  
        {  
            return num-48;  
        }  
        else if(num>=97&&num<=122)  
        {  
            return num-87;  
        }else if(num>=65&&num<=90)  
        {  
            return num-29;  
        }else if(num==43)  
        {  
            return 62;  
        }  
        else if (num == 47)  
        {  
            return 63;  
        }  
        return 0;  
    }  
  
}  
 

    /// <summary>
    /// Base64编码类。
    /// 将byte[]类型转换成Base64编码的string类型。
    /// </summary>
    public class MyBase64Encoder
    {
        byte[] source;
        int length, length2;
        int blockCount;
        int paddingCount;
        public static MyBase64Encoder Encoder = new MyBase64Encoder();

        public MyBase64Encoder()
        {
        }

        private void init(byte[] input)
        {
            source = input;
            length = input.Length;
            if ((length % 3) == 0)
            {
                paddingCount = 0;
                blockCount = length / 3;
            }
            else
            {
                paddingCount = 3 - (length % 3);
                blockCount = (length + paddingCount) / 3;
            }
            length2 = length + paddingCount;
        }

        public string GetEncoded(byte[] input)
        {
            //初始化
            init(input);

            byte[] source2;
            source2 = new byte[length2];

            for (int x = 0; x < length2; x++)
            {
                if (x < length)
                {
                    source2[x] = source[x];
                }
                else
                {
                    source2[x] = 0;
                }
            }

            byte b1, b2, b3;
            byte temp, temp1, temp2, temp3, temp4;
            byte[] buffer = new byte[blockCount * 4];
            char[] result = new char[blockCount * 4];
            for (int x = 0; x < blockCount; x++)
            {
                b1 = source2[x * 3];
                b2 = source2[x * 3 + 1];
                b3 = source2[x * 3 + 2];

                temp1 = (byte)((b1 & 252) >> 2);

                temp = (byte)((b1 & 3) << 4);
                temp2 = (byte)((b2 & 240) >> 4);
                temp2 += temp;

                temp = (byte)((b2 & 15) << 2);
                temp3 = (byte)((b3 & 192) >> 6);
                temp3 += temp;

                temp4 = (byte)(b3 & 63);

                buffer[x * 4] = temp1;
                buffer[x * 4 + 1] = temp2;
                buffer[x * 4 + 2] = temp3;
                buffer[x * 4 + 3] = temp4;

            }

            for (int x = 0; x < blockCount * 4; x++)
            {
                result[x] = sixbit2char(buffer[x]);
            }


            switch (paddingCount)
            {
                case 0: break;
                case 1: result[blockCount * 4 - 1] = '='; break;
                case 2: result[blockCount * 4 - 1] = '=';
                    result[blockCount * 4 - 2] = '=';
                    break;
                default: break;
            }
            return new string(result);
        }
        private char sixbit2char(byte b)
        {
            char[] lookupTable = new char[64]{
                  'A','B','C','D','E','F','G','H','I','J','K','L','M',
                 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
                 'a','b','c','d','e','f','g','h','i','j','k','l','m',
                 'n','o','p','q','r','s','t','u','v','w','x','y','z',
                 '0','1','2','3','4','5','6','7','8','9','!','@'};

            if ((b >= 0) && (b <= 63))
            {
                return lookupTable[(int)b];
            }
            else
            {

                return ' ';
            }
        }

    }

    /// <summary>
    /// Base64解码类
    /// 将Base64编码的string类型转换成byte[]类型
    /// </summary>
    public class MyBase64Decoder
    {
        char[] source;
        int length, length2, length3;
        int blockCount;
        int paddingCount;
        public static MyBase64Decoder Decoder = new MyBase64Decoder();

        public MyBase64Decoder()
        {
        }

        private void init(char[] input)
        {
            int temp = 0;
            source = input;
            length = input.Length;

            for (int x = 0; x < 2; x++)
            {
                if (input[length - x - 1] == '=')
                    temp++;
            }
            paddingCount = temp;

            blockCount = length / 4;
            length2 = blockCount * 3;
        }

        public byte[] GetDecoded(string strInput)
        {
            //初始化
            init(strInput.ToCharArray());

            byte[] buffer = new byte[length];
            byte[] buffer2 = new byte[length2];

            for (int x = 0; x < length; x++)
            {
                buffer[x] = char2sixbit(source[x]);
            }

            byte b, b1, b2, b3;
            byte temp1, temp2, temp3, temp4;

            for (int x = 0; x < blockCount; x++)
            {
                temp1 = buffer[x * 4];
                temp2 = buffer[x * 4 + 1];
                temp3 = buffer[x * 4 + 2];
                temp4 = buffer[x * 4 + 3];

                b = (byte)(temp1 << 2);
                b1 = (byte)((temp2 & 48) >> 4);
                b1 += b;

                b = (byte)((temp2 & 15) << 4);
                b2 = (byte)((temp3 & 60) >> 2);
                b2 += b;

                b = (byte)((temp3 & 3) << 6);
                b3 = temp4;
                b3 += b;

                buffer2[x * 3] = b1;
                buffer2[x * 3 + 1] = b2;
                buffer2[x * 3 + 2] = b3;
            }

            length3 = length2 - paddingCount;
            byte[] result = new byte[length3];

            for (int x = 0; x < length3; x++)
            {
                result[x] = buffer2[x];
            }

            return result;
        }

        private byte char2sixbit(char c)
        {
            char[] lookupTable = new char[64]{  
                 'A','B','C','D','E','F','G','H','I','J','K','L','M','N',
                 'O','P','Q','R','S','T','U','V','W','X','Y', 'Z',
                 'a','b','c','d','e','f','g','h','i','j','k','l','m','n',
                 'o','p','q','r','s','t','u','v','w','x','y','z',
                 '0','1','2','3','4','5','6','7','8','9','!','@'};
            if (c == '=')
                return 0;
            else
            {
                for (int x = 0; x < 64; x++)
                {
                    if (lookupTable[x] == c)
                        return (byte)x;
                }

                return 0;
            }

        }

    }
}
